import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter_module/common/http/http_error.dart';
import 'package:flutter_module/common/http/request/base_request.dart';
import 'package:flutter_module/core/flutter_bridge.dart';

/// Create by kyluzoi
/// Date: 2021-07-30
///
/// Description: http 封装  底层采用 Dio  , 暂时未采用拦截器机制

class YiHttp {
  YiHttp._();

  static YiHttp? _instance;

  static YiHttp getInstance() {
    if (_instance == null) {
      HttpOverrides.global = new MyHttpOverrides();
      _instance = YiHttp._();
    }
    return _instance!;
  }

  Future request(BaseRequest request) async {
    if (request.requestMethod() == RequestMethod.GET) {
      return _doGet(request);
    } else {
      return _doPost(request);
    }
  }

  Future _doPost(BaseRequest request) async {
    //这块参照 Dio 源码去设计
    var uri = await _uriParse(request);
    var header, response;
    header = await FlutterPlatformBridge.getInstance().getHeaderParams();

    var dio = Dio();
    if (request.isJson()) {
      response = await dio.post(uri.toString(),
          data: request.bodyParams,
          options: Options(headers: header, responseType: ResponseType.json));
    } else {
      // form 表单
      FormData formData = FormData.fromMap(request.bodyParams);
      response = await dio.post(uri.toString(),
          data: formData,
          options: Options(headers: header, responseType: ResponseType.json));
    }

    return _statusCodeConver(response);
  }

  Future _doGet(BaseRequest request) async {
    var uri = await _uriParse(request);

    var header = await FlutterPlatformBridge.getInstance().getHeaderParams();

    /// 采用 Dio 进行请求 未来有更好的网络框架，可替换
    var response = await Dio().get(uri.toString(),
        options: Options(headers: header, responseType: ResponseType.json));

    return _statusCodeConver(response);
  }

  Future _businessConver(var result) async {
    if (result["code"] == 200) {
      return result["data"];
    } else {
      throw NetWorkBaseError(result["code"], result["message"]);
    }
  }

  Future _statusCodeConver(var response) async {
    var result = response.data;
    if (response.statusCode == 200) {
      // http 请求状态码判断
      return _businessConver(result);
    } else if (response.statusCode == 401) {
      throw UnLoginError();
    } else if (response.statusCode == 403) {
      throw UnAuthError();
    } else {
      throw Exception(
          'statusCode:${response.statusCode},message:${result.toString()}');
    }
  }

  Future<Uri> _uriParse(BaseRequest request) async {
    var uri;
    var url = await request.url();
    if (url.startsWith("http://")) {
      if (request.queryParams.length != 0) {
        uri = Uri.http(
            url.split("http://")[1], request.path(), request.queryParams);
      } else {
        uri = Uri.http(url.split("http://")[1], request.path());
      }
    } else {
      // 没指定 默认拼接 https
      if (request.queryParams.length != 0) {
        uri = Uri.https(
            url.split("https://")[1], request.path(), request.queryParams);
      } else {
        uri = Uri.https(url.split("https://")[1], request.path());
      }
    }

    return uri;
  }
}

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
  }
}
